import os
import sys
import logging
import json
import pandas as pd
import argparse
from datetime import datetime

# 添加项目根目录到系统路径
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

from src.data_collection.job_crawler import JobCrawler
from src.data_collection.report_parser import ReportParser
from src.analysis.trend_engine import TrendEngine
from src.analysis.skill_diagnosis import SkillDiagnosisSystem
from src.recommendation.career_path import CareerPathRecommender
from src.recommendation.learning_plan import LearningPlanGenerator
from src.utils.nlp_utils import NLPUtils
from config import CONFIG

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler("career_ai_system.log"),
        logging.StreamHandler()
    ]
)

logger = logging.getLogger(__name__)

class CareerAISystem:
    """职业发展智能匹配系统主类"""
    
    def __init__(self, config=None):
        self.config = config or CONFIG
        
        # 初始化各模块
        logger.info("初始化系统模块...")
        self.job_crawler = JobCrawler(self.config)
        self.report_parser = ReportParser(self.config)
        self.trend_engine = TrendEngine(self.config)
        self.skill_diagnosis = SkillDiagnosisSystem(self.config)
        self.career_path = CareerPathRecommender(self.config)
        self.learning_plan = LearningPlanGenerator(self.config)
        self.nlp_utils = NLPUtils(self.config)
        
        # 创建数据目录
        os.makedirs("data", exist_ok=True)
        
        logger.info("系统初始化完成")
    
    def crawl_job_data(self):
        """爬取职位数据"""
        logger.info("开始爬取职位数据...")
        
        # 从配置中获取关键词
        keywords = []
        for industry, terms in self.config.get('INDUSTRY_MAPPING', {}).items():
            keywords.append(industry)
            keywords.extend(terms[:2])  # 只取前两个相关词
        
        # 去重
        keywords = list(set(keywords))
        
        # 尝试从猎聘网爬取数据
        try:
            jobs_df = self.job_crawler.scrape_liepin_jobs(keywords, pages=2)
        except Exception as e:
            logger.error(f"爬取猎聘网数据失败: {str(e)}")
            logger.info("使用离线数据集...")
            jobs_df = self.job_crawler.load_job_dataset(keywords=keywords)
        
        # 生成文件路径
        timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
        filename = f"data/jobs_{timestamp}.csv"
        
        # 保存数据
        jobs_df.to_csv(filename, index=False, encoding='utf-8')
        logger.info(f"职位数据已保存至: {filename}")
        
        return filename
    
    def parse_industry_reports(self, report_dir="data/reports"):
        """解析行业报告（Streamlit界面调用）
        
        Args:
            report_dir (str): 报告目录
            
        Returns:
            str: 生成的趋势数据文件路径
        """
        logger.info(f"开始从目录 {report_dir} 提取行业趋势...")
        
        try:
            # 确保目录存在
            os.makedirs(report_dir, exist_ok=True)
            
            # 调用report_parser提取趋势
            trends_df = self.report_parser.extract_industry_trends(report_dir)
            
            # 保存趋势数据
            timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
            filename = f"data/trends_{timestamp}.csv"
            
            # 确保数据目录存在
            os.makedirs("data", exist_ok=True)
            
            trends_df.to_csv(filename, index=False, encoding='utf-8')
            logger.info(f"行业趋势数据已保存至: {filename}")
            
            return filename
        except Exception as e:
            logger.error(f"行业报告提取失败: {str(e)}")
            return None
    
    def analyze_trends(self, jobs_file, trends_file):
        """分析行业趋势
        
        Args:
            jobs_file (str): 职位数据文件
            trends_file (str): 趋势数据文件
            
        Returns:
            str: 趋势报告文件路径
        """
        logger.info("开始分析行业趋势...")
        
        # 加载数据
        jobs_df, trends_df = self.trend_engine.load_data(jobs_file, trends_file)
        
        if jobs_df.empty or trends_df.empty:
            logger.error("数据加载失败")
            return None
        
        # 分析热门技能
        hot_skills = self.trend_engine.analyze_hot_skills(jobs_df)
        
        # 识别增长领域
        growth_areas = self.trend_engine.identify_growth_areas(jobs_df, trends_df)
        
        # 生成趋势报告
        report = self.trend_engine.generate_trend_report(hot_skills, growth_areas)
        
        timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
        filename = f"data/trend_report_{timestamp}.md"
        
        with open(filename, 'w', encoding='utf-8') as f:
            f.write(report)
            
        logger.info(f"趋势报告已生成: {filename}")
        
        # 保存分析结果供后续使用
        result = {
            'hot_skills': hot_skills,
            'growth_areas': growth_areas
        }
        
        result_filename = f"data/trend_analysis_{timestamp}.json"
        with open(result_filename, 'w', encoding='utf-8') as f:
            json.dump(result, f, ensure_ascii=False, indent=2)
            
        logger.info(f"趋势分析结果已保存: {result_filename}")
        
        return filename, result_filename
    
    def analyze_resume(self, resume_text):
        """分析简历
        
        Args:
            resume_text (str): 简历文本
            
        Returns:
            dict: 用户技能
        """
        logger.info("开始分析简历...")
        
        user_skills = self.skill_diagnosis.analyze_resume(resume_text)
        
        timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
        filename = f"data/user_skills_{timestamp}.json"
        
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(user_skills, f, ensure_ascii=False, indent=2)
            
        logger.info(f"用户技能已保存: {filename}")
        
        return user_skills, filename
    
    def analyze_job(self, job_description):
        """分析职位描述
        
        Args:
            job_description (str): 职位描述
            
        Returns:
            dict: 职位所需技能
        """
        logger.info("开始分析职位描述...")
        
        job_skills = self.skill_diagnosis.analyze_job_requirements(job_description)
        
        timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
        filename = f"data/job_skills_{timestamp}.json"
        
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(job_skills, f, ensure_ascii=False, indent=2)
            
        logger.info(f"职位技能需求已保存: {filename}")
        
        return job_skills, filename
    
    def generate_skill_gap_analysis(self, user_skills, job_skills):
        """生成技能差距分析
        
        Args:
            user_skills (dict/tuple): 用户技能及水平
            job_skills (dict/tuple): 职位所需技能及水平
            
        Returns:
            tuple: (分析结果, 保存的JSON文件路径, 可视化图片路径)
        """
        try:
            # 处理user_skills元组
            if isinstance(user_skills, tuple):
                if len(user_skills) > 0:
                    user_skills = user_skills[0]  # 提取元组中的第一个元素（字典）
                else:
                    logger.warning("user_skills元组为空")
                    user_skills = {}
                    
            # 处理job_skills元组
            if isinstance(job_skills, tuple):
                if len(job_skills) > 0:
                    job_skills = job_skills[0]  # 提取元组中的第一个元素（字典）
                else:
                    logger.warning("job_skills元组为空")
                    job_skills = {}
                    
            # 确保处理后的数据是字典
            if not isinstance(user_skills, dict):
                logger.warning(f"user_skills不是字典类型: {type(user_skills)}")
                user_skills = {"skills": {}}
                
            if not isinstance(job_skills, dict):
                logger.warning(f"job_skills不是字典类型: {type(job_skills)}")
                job_skills = {"skills": {}}
            
            # 继续处理字典情况
            if 'skills' in user_skills:
                user_skills = user_skills['skills']
            
            if 'skills' in job_skills:
                job_skills = job_skills['skills']
                
            # 最后确认数据是字典，若不是则创建空字典
            if not isinstance(user_skills, dict):
                user_skills = {}
            if not isinstance(job_skills, dict):
                job_skills = {}
            
            # 确保没有技能的水平被设置为0
            for skill, level in list(user_skills.items()):
                if level <= 0:
                    user_skills[skill] = 50  # 设置一个基础分数
            
            # 生成差距分析
            gap_analysis = self.skill_diagnosis.generate_skill_gap_analysis(user_skills, job_skills)
            
            # 保存分析结果
            timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
            gap_file = f"data/skill_gap_{timestamp}.json"
            os.makedirs(os.path.dirname(gap_file), exist_ok=True)
            
            with open(gap_file, 'w', encoding='utf-8') as f:
                json.dump(gap_analysis, f, ensure_ascii=False, indent=2)
            
            # 生成可视化
            gap_viz = self.skill_diagnosis.visualize_skill_gap(user_skills, job_skills)
            
            return gap_analysis, gap_file, gap_viz
            
        except Exception as e:
            logger.error(f"技能差距分析错误: {str(e)}")
            return None, None, None
    
    def recommend_career_paths(self, user_skills, growth_areas, career_goals):
        """推荐职业发展路径
        
        Args:
            user_skills: 用户技能评估
            growth_areas: 行业增长领域
            career_goals: 职业目标描述
            
        Returns:
            tuple: (推荐的职业路径列表, 保存的JSON文件路径)
        """
        logger.info("开始推荐职业发展路径...")
        
        try:
            # 获取职业路径
            paths = self.career_path.recommend_career_paths(user_skills, growth_areas, career_goals)
            
            # 保存结果
            timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
            paths_file = f"data/career_paths_{timestamp}.json"
            
            # 确保目录存在
            os.makedirs("data", exist_ok=True)
            
            # 保存到文件
            with open(paths_file, 'w', encoding='utf-8') as f:
                json.dump(paths, f, ensure_ascii=False, indent=2)
            
            logger.info(f"职业路径推荐已保存: {paths_file}")
            return paths, paths_file
            
        except Exception as e:
            logger.error(f"职业路径推荐失败: {str(e)}")
            return [], None
    
    def generate_learning_plan(self, gap_analysis_file, career_goals, timeline_months=3):
        """生成学习计划
        
        Args:
            gap_analysis_file (str): 技能差距分析文件
            career_goals (str): 职业目标描述
            timeline_months (int): 计划时间线（月）
            
        Returns:
            dict: 学习计划
        """
        logger.info("开始生成学习计划...")
        
        # 加载技能差距分析
        with open(gap_analysis_file, 'r', encoding='utf-8') as f:
            gap_analysis = json.load(f)
            
        # 生成学习计划
        learning_plan = self.learning_plan.generate_learning_plan(
            gap_analysis, 
            career_goals, 
            timeline_months
        )
        
        timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
        filename = f"data/learning_plan_{timestamp}.json"
        
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(learning_plan, f, ensure_ascii=False, indent=2)
            
        logger.info(f"学习计划已保存: {filename}")
        
        # 生成计划摘要
        summary = self.learning_plan.generate_plan_summary(learning_plan)
        
        summary_filename = f"data/learning_plan_summary_{timestamp}.md"
        with open(summary_filename, 'w', encoding='utf-8') as f:
            f.write(summary)
            
        logger.info(f"学习计划摘要已生成: {summary_filename}")
        
        # 可视化学习计划
        plan_viz = self.learning_plan.visualize_learning_plan(learning_plan)
        if plan_viz:
            logger.info(f"学习计划可视化已生成: {plan_viz}")
            
        return learning_plan, filename, summary_filename, plan_viz
    
    def run_full_pipeline(self, resume_text, job_description, career_goals, timeline):
        """运行完整的分析流程
        
        Args:
            resume_text (str): 简历文本
            job_description (str): 职位描述
            career_goals (str): 职业目标
            timeline (int): 学习计划时长(月)
            
        Returns:
            dict: 包含所有分析结果的字典
        """
        try:
            # 执行各个分析步骤
            logger.info("开始全流程分析")
            
            # 1. 技能诊断 - 分析简历和职位
            user_skills, job_skills, match_analysis = self.skill_diagnosis.analyze_resume_and_job_together(
                resume_text, job_description
            )
            
            # 安全检查: 确保返回的结果是字典类型
            if not isinstance(user_skills, dict):
                logger.error(f"user_skills 不是字典类型: {type(user_skills)}")
                user_skills = {}
            if not isinstance(job_skills, dict):
                logger.error(f"job_skills 不是字典类型: {type(job_skills)}")
                job_skills = {}
            if not isinstance(match_analysis, dict):
                logger.error(f"match_analysis 不是字典类型: {type(match_analysis)}")
                match_analysis = {'overall_match': 0, 'match_analysis': {}}
            
            # 2. 行业趋势分析 - 添加更好的错误处理
            try:
                # 检查方法是否存在
                if hasattr(self.trend_engine, 'analyze_industry_trends'):
                    trend_analysis = self.trend_engine.analyze_industry_trends(job_description)
                else:
                    logger.error("TrendEngine类没有analyze_industry_trends方法")
                    # 提供默认结果
                    trend_analysis = {
                        'industry': '信息技术',
                        'hot_skills': [],
                        'emerging_technologies': [],
                        'outlook': '该行业持续稳定发展'
                    }
            except Exception as e:
                logger.error(f"行业趋势分析出错: {str(e)}")
                trend_analysis = {
                    'industry': '信息技术',
                    'hot_skills': [],
                    'emerging_technologies': [],
                    'outlook': '该行业持续稳定发展'
                }
            
            # 确保trend_analysis是字典类型
            if not isinstance(trend_analysis, dict):
                logger.error(f"trend_analysis 不是字典类型: {type(trend_analysis)}")
                trend_analysis = {}
            
            # 3. 职业路径推荐
            career_paths = self.career_path.recommend_career_paths(user_skills, job_skills, career_goals)
            if not isinstance(career_paths, (list, dict)):
                logger.error(f"career_paths 不是列表或字典类型: {type(career_paths)}")
                career_paths = []
            
            # 4. 学习计划生成 - 修正参数传递方式
            try:
                # 正确调用学习计划生成方法
                # 根据参数定义正确传参：应该传入(gap_analysis, career_goals, timeline)
                learning_plan = self.learning_plan.generate_learning_plan(
                    match_analysis,  # 使用匹配分析结果替代差距分析文件
                    career_goals,    # 职业目标
                    timeline         # 时间线
                )
                if not isinstance(learning_plan, dict):
                    logger.error(f"learning_plan 不是字典类型: {type(learning_plan)}")
                    learning_plan = {}
                    
            except TypeError as e:
                logger.error(f"学习计划生成参数错误: {str(e)}")
                # 尝试另一种可能的参数组合（如果LearningPlanGenerator有两种不同的实现）
                try:
                    # 备选方案：尝试使用不同的参数组合
                    learning_plan = self.learning_plan.generate_learning_plan(
                        user_skills,
                        job_skills,
                        career_goals, 
                        timeline
                    )
                except Exception as e2:
                    logger.error(f"备选学习计划生成也失败: {str(e2)}")
                    learning_plan = {
                        "error": "学习计划生成失败",
                        "skills_plan": [],
                        "timeline": timeline,
                        "resources": []
                    }
            except Exception as e:
                logger.error(f"学习计划生成失败: {str(e)}")
                learning_plan = {
                    "error": "学习计划生成失败",
                    "skills_plan": [],
                    "timeline": timeline,
                    "resources": []
                }
            
            # 汇总所有结果
            results = {
                'user_skills': user_skills,
                'job_skills': job_skills,
                'match_analysis': match_analysis,
                'trend_analysis': trend_analysis,
                'career_paths': career_paths,
                'learning_plan': learning_plan,
                'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            }
            
            logger.info("全流程分析完成")
            return results
            
        except Exception as e:
            logger.error(f"全流程分析出错: {str(e)}")
            # 返回包含错误信息的字典，而不是直接抛出异常
            return {
                'error': str(e),
                'user_skills': {},
                'job_skills': {},
                'match_analysis': {'overall_match': 0, 'match_analysis': {}},
                'trend_analysis': {},
                'career_paths': [],
                'learning_plan': {},
                'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            }
    
    def analyze_resume_and_job_together(self, resume_text, job_description):
        """同时分析简历和职位描述，确保技能名称一致性
        
        Args:
            resume_text (str): 简历文本内容
            job_description (str): 职位描述文本
            
        Returns:
            tuple: (用户技能字典, 职位技能字典, 匹配分析)
        """
        try:
            # 调用技能诊断系统中的同名方法
            return self.skill_diagnosis.analyze_resume_and_job_together(resume_text, job_description)
        except Exception as e:
            logger.error(f"联合分析简历和职位描述出错: {str(e)}")
            # 出错时返回空结果
            return {}, {}, {}
    
    def visualize_skill_gap(self, user_skills, job_skills, output_path=None):
        """可视化技能差距
        
        Args:
            user_skills (dict): 用户技能
            job_skills (dict): 职位要求技能
            output_path (str, optional): 输出文件路径
            
        Returns:
            str: 图表保存路径
        """
        try:
            # 调用技能诊断系统中的同名方法
            return self.skill_diagnosis.visualize_skill_gap(user_skills, job_skills, output_path)
        except Exception as e:
            logger.error(f"技能差距可视化错误: {str(e)}")
            return None

def main():
    """主函数"""
    parser = argparse.ArgumentParser(description="职业发展智能匹配系统")
    
    # 子命令
    subparsers = parser.add_subparsers(dest="command", help="命令")
    
    # 爬取职位数据命令
    crawl_parser = subparsers.add_parser("crawl", help="爬取职位数据")
    crawl_parser.add_argument("--keywords", nargs="+", help="搜索关键词列表")
    crawl_parser.add_argument("--pages", type=int, default=5, help="每个关键词爬取的页数")
    
    # 解析报告命令
    parse_parser = subparsers.add_parser("parse", help="解析行业报告")
    parse_parser.add_argument("--dir", default="data/reports", help="报告目录")
    
    # 分析行业趋势命令
    trend_parser = subparsers.add_parser("trend", help="分析行业趋势")
    trend_parser.add_argument("--jobs", required=True, help="职位数据文件")
    trend_parser.add_argument("--trends", required=True, help="趋势数据文件")
    
    # 分析简历命令
    resume_parser = subparsers.add_parser("resume", help="分析简历")
    resume_parser.add_argument("--file", required=True, help="简历文件")
    
    # 分析职位命令
    job_parser = subparsers.add_parser("job", help="分析职位描述")
    job_parser.add_argument("--file", required=True, help="职位描述文件")
    
    # 技能差距分析命令
    gap_parser = subparsers.add_parser("gap", help="生成技能差距分析")
    gap_parser.add_argument("--user", required=True, help="用户技能文件")
    gap_parser.add_argument("--job", required=True, help="职位技能文件")
    
    # 推荐职业路径命令
    path_parser = subparsers.add_parser("path", help="推荐职业发展路径")
    path_parser.add_argument("--skills", required=True, help="用户技能文件")
    path_parser.add_argument("--trends", required=True, help="趋势分析文件")
    path_parser.add_argument("--jobs", required=True, help="职位数据文件")
    
    # 生成学习计划命令
    plan_parser = subparsers.add_parser("plan", help="生成学习计划")
    plan_parser.add_argument("--gap", required=True, help="技能差距分析文件")
    plan_parser.add_argument("--goals", required=True, help="职业目标")
    plan_parser.add_argument("--months", type=int, default=3, help="计划时间线（月）")
    
    # 完整流程命令
    pipeline_parser = subparsers.add_parser("pipeline", help="运行完整流程")
    pipeline_parser.add_argument("--resume", required=True, help="简历文件")
    pipeline_parser.add_argument("--job", required=True, help="职位描述文件")
    pipeline_parser.add_argument("--goals", required=True, help="职业目标")
    pipeline_parser.add_argument("--months", type=int, default=3, help="计划时间线（月）")
    
    # 解析参数
    args = parser.parse_args()
    
    # 创建系统实例
    system = CareerAISystem()
    
    # 根据命令执行相应功能
    if args.command == "crawl":
        system.crawl_job_data()
    
    elif args.command == "parse":
        system.parse_industry_reports(args.dir)
    
    elif args.command == "trend":
        system.analyze_trends(args.jobs, args.trends)
    
    elif args.command == "resume":
        with open(args.file, 'r', encoding='utf-8') as f:
            resume_text = f.read()
        system.analyze_resume(resume_text)
    
    elif args.command == "job":
        with open(args.file, 'r', encoding='utf-8') as f:
            job_description = f.read()
        system.analyze_job(job_description)
    
    elif args.command == "gap":
        with open(args.user, 'r', encoding='utf-8') as f:
            user_skills = json.load(f)
        with open(args.job, 'r', encoding='utf-8') as f:
            job_skills = json.load(f)
        system.generate_skill_gap_analysis(user_skills, job_skills)
    
    elif args.command == "path":
        system.recommend_career_paths(args.skills, args.trends, args.goals)
    
    elif args.command == "plan":
        system.generate_learning_plan(args.gap, args.goals, args.months)
    
    elif args.command == "pipeline":
        with open(args.resume, 'r', encoding='utf-8') as f:
            resume_text = f.read()
        with open(args.job, 'r', encoding='utf-8') as f:
            job_description = f.read()
        system.run_full_pipeline(resume_text, job_description, args.goals, args.months)
    
    else:
        parser.print_help()

if __name__ == "__main__":
    main() 